package com.atguigu.tingshu.album.service.impl;

import com.alibaba.nacos.shaded.javax.annotation.Nullable;
import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.AlbumAttributeValueService;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.lang.model.SourceVersion;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private AlbumAttributeValueService albumAttributeValueService;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 保存专辑方法
     *
     * @param albumInfoVo
     * @param userId      -- 可以暂时写个固定值
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
        //	创建专辑对象
        AlbumInfo albumInfo = new AlbumInfo();
        //	属性拷贝
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        //	设置专辑审核状态为：通过
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        //	设置用户Id
        albumInfo.setUserId(userId);
        //  付费的默认前前5集免费试看
        if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
            albumInfo.setTracksForFree(5);
        }
        //	保存专辑
        this.save(albumInfo);
        if ("1".equals(albumInfo.getIsOpen())) {
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
        }
        //	保存专辑属性值：
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        //	判断
        if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
            // 循环遍历
            List<AlbumAttributeValue> attributeValueList = albumAttributeValueVoList.stream().map(albumAttributeValueVo -> {
                // 创建一个实体对象
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                // 属性拷贝
                BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
                albumAttributeValue.setAlbumId(albumInfo.getId());
                return albumAttributeValue;
            }).collect(Collectors.toList());
            //批量插入
            this.albumAttributeValueService.saveBatch(attributeValueList);
        }


        //初始化统计数据
        //播放量
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);
        //订阅量
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
        //购买量
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);
        //评论数
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);

    }

    /**
     * 初始化统计数据
     *
     * @param albumId
     * @param statType
     */
    private void saveAlbumStat(Long albumId, String statType) {
        AlbumStat albumStat = new AlbumStat();
        albumStat.setAlbumId(albumId);
        albumStat.setStatType(statType);
        albumStat.setStatNum(new Random().nextInt(10000000));
        albumStatMapper.insert(albumStat);
    }


    @Override
    public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> albumInfoPage, AlbumInfoQuery albumInfoQuery) {
        //	调用mapper 层方法
        return albumInfoMapper.selectUserAlbumPage(albumInfoPage, albumInfoQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeAlbumInfoById(Long id) {
        // 查询专辑下是否包含声音
        LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TrackInfo::getAlbumId, id);
        Long count = trackInfoMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new GuiguException(400, "专辑下有声音，请先删除专辑下的声音");
        }
        //	删除专辑表的数据 album_info
        this.removeById(id);
        //	删除专辑属性信息
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>()
                .eq(AlbumAttributeValue::getAlbumId, id));
        //	删除专辑对应的统计数据
        albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, id));
        //下架
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, id);
    }

    @GuiGuCache(prefix = RedisConstant.ALBUM_INFO_PREFIX)
    @Override
    public AlbumInfo getAlbumInfoById(Long id) {
     /*   //	创建专辑对象
        AlbumInfo albumInfo = new AlbumInfo();
        //	声明缓存key
        String albumKey = RedisConstant.ALBUM_INFO_PREFIX + id;
        try {
            albumInfo = (AlbumInfo) redisTemplate.opsForValue().get(albumKey);
            if (null == albumInfo) {
                //	查询数据库，声明锁
                String albumLockKey = RedisConstant.ALBUM_INFO_PREFIX + id + ":lock";
                //	获取锁对象
                RLock lock = redissonClient.getLock(albumLockKey);
                boolean result = lock.tryLock(RedisConstant.ALBUM_LOCK_EXPIRE_PX1, RedisConstant.ALBUM_LOCK_EXPIRE_PX2, TimeUnit.SECONDS);
                if (result) {
                    try {
                        //	获取到锁
                        albumInfo = getAlbumInfoDB(id);
                        if (null == albumInfo) {
                            //	设置控制存储到缓存
                            AlbumInfo albumInfo1 = new AlbumInfo();
                            redisTemplate.opsForValue().set(albumKey, albumInfo1, RedisConstant.ALBUM_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
                            return albumInfo1;
                        }
                        //	将数据写入缓存
                        redisTemplate.opsForValue().set(albumKey, albumInfo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS);
                        return albumInfo;
                    } finally {
                        //	使用lua脚本删除锁
                        lock.unlock();
                    }
                } else {
                    //	没有获取到锁的线程，自旋
                    return getAlbumInfoById(id);
                }
            } else {
                //	缓存不为空，直接返回数据
                return albumInfo;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        //	如果有异常，最后查询数据库
        return getAlbumInfoDB(id);
    }

    @Nullable
    private AlbumInfo getAlbumInfoDB(Long albumId) {
        //  因为需要给专辑标签赋值; albumAttributeValueVoList
        //  查询专辑信息表;
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //  为了防止空指针
        if (null != albumInfo) {
            //  根据专辑Id获取到标签数据：
            //  select * from album_attribute_value where album_id = 1630 ;
            //  Warpper 构建查询条件的;
            LambdaQueryWrapper<AlbumAttributeValue> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AlbumAttributeValue::getAlbumId, albumId);
            List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(wrapper);
            albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);
        }
        //  返回数据
        return albumInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAlbumInfo(Long id, AlbumInfoVo albumInfoVo) {
        //先删除缓存的key:album_info:id
        String dataKey = RedisConstant.ALBUM_INFO_PREFIX + "["+id+"]";
        System.out.println("AlbumInfoServiceImpl.updateAlbumInfo=================================================="+dataKey);
        redisTemplate.delete(dataKey);
        AlbumInfo albumInfo = new AlbumInfo();
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        albumInfo.setId(id);
        //	根据id 修改数据
        this.updateById(albumInfo);
        //	先删除专辑标签数据
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
        //	保存专辑属性数据
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
            for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
                //	创建专辑属性对象
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                //	进行数据拷贝
                BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
                //	赋值专辑属性Id
                albumAttributeValue.setAlbumId(id);
                albumAttributeValueMapper.insert(albumAttributeValue);
            }
        }
        //	更新上架下架
        if ("1".equals(albumInfo.getIsOpen())) {
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, id);
        } else {
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, id);
        }
        try {
            Thread.sleep(1000);
        }catch (InterruptedException e){
            throw new RuntimeException(e);
        }
        //删除
        redisTemplate.delete(dataKey);
    }

    @Override
    public List<AlbumInfo> findUserAllAlbumList(Long userId) {
        //  构建查询条件;
        LambdaQueryWrapper<AlbumInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AlbumInfo::getUserId, userId);
        wrapper.orderByDesc(AlbumInfo::getId);
        Page<AlbumInfo> albumInfoPage = new Page<>(1, 100);
        //  List<AlbumInfo> albumInfoList = albumInfoMapper.selectList(wrapper);
        Page<AlbumInfo> infoPage = albumInfoMapper.selectPage(albumInfoPage, wrapper);
        //  返回专辑列表
        return infoPage.getRecords();
    }

    @Override
    public List<AlbumAttributeValue> findAlbumAttributeValueByAlbumId(Long albumId) {
        LambdaQueryWrapper<AlbumAttributeValue> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AlbumAttributeValue::getAlbumId, albumId);
        List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(lambdaQueryWrapper);

        //返回集合数据
        return albumAttributeValueList;
    }

    @Override
    public AlbumStatVo getAlbumStat(Long albumId) {
        AlbumStatVo albumStatVo = albumInfoMapper.getAlbumStat(albumId);
        return albumStatVo;
    }

    @GuiGuCache(prefix = "albumStat")
    @Override
    public AlbumStatVo getAlbumStatVoByAlbumId(Long albumId) {
        //调用mapper 层方法
        return albumInfoMapper.selectAlbumStat(albumId);
    }
}
